package com.inzone.fram.gray.config;

import com.inzone.fram.gray.common.rule.MatchingContext;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.Callable;

/**
 * 熔断器线程隔离模式应传递线程上下文
 *
 * @author 丁常磊
 * @date 2021/10/15 20:13
 */

@Configuration
@ConditionalOnClass({
        HystrixConcurrencyStrategy.class
})
public class MatchingHystrixConfig {

    @Bean
    public HystrixConcurrencyStrategy hystrixConcurrencyStrategy() {

        return new HystrixConcurrencyStrategy() {
            @Override
            public <T> Callable<T> wrapCallable(Callable<T> callable) {
                if (MatchingContext.isInitialized()) {

                    //取出当前上下文
                    MatchingContext current = MatchingContext.current();
                    Callable<T> tCallable = super.wrapCallable(callable);
                    return () -> {
                        //强制设置给当前线程
                        MatchingContext.forceSetCurrent(current);
                        try {
                            return tCallable.call();
                        } finally {
                            //重置
                            MatchingContext.reset();
                        }
                    };

                } else {
                    return super.wrapCallable(callable);
                }
            }
        };
    }

}
